import { configMap, createNamedStore } from "../../config/index.js"
import { selectFans, insertOrUpdateFans, getChatRecord, saveChatRecord, generateChatContent, uploadImag, checkKeyWordAndImg } from "../../api/webApi/index.js"
import { getRandomInteger, arrayToValueOfConfig, closeUnwantedPages, generatePositiveInt64, replacePlaceholder, downloadCdnResource } from "../../utils/index.js"
// 创建本地缓存存储实例用于记录评论任务运行周期
export const tkLiveHomeFollowStore = createNamedStore("tk-live-home-follow")
export async function tk_live_home_follow_main(task, browser, index, taskId, collectPlatformParams) {
  // 创建结果对象
  const result = {
    success: false,
    message: "",
    taskId,
    commentedCount: 0,
  }
  console.log("tk直播间找粉丝")
  // 当前策略的运行时间段
  const ranges = task?.operatingTimeRanges?.ranges || []
  console.log("tk_live_home_follow_main=ranges===>", ranges)
  const composedTask = task.composedTask
  // 获取运行配置
  const config = composedTask.config || []
  // 获取当前的关注上限数量
  const _limitNum = arrayToValueOfConfig(config, "limit_num") || 0
  // 获取当前的回复上限数量
  const _replyLimitNum = arrayToValueOfConfig(config, "limit_replay_num") || 0
  // 直播间礼物榜送出金币最小个数（个）
  const _liveHomeSendCionNumLimit = arrayToValueOfConfig(config, "live_home_send_cion_num_limit") || 0
  // 获取搜索关键字
  const keywords = arrayToValueOfConfig(config, "keywords")

  console.log("_limitNum===>", _limitNum)
  console.log("_replyLimitNum===>", _replyLimitNum)
  console.log("_liveHomeSendCionNumLimit===>", _liveHomeSendCionNumLimit)
  console.log("keywords===>", keywords)
  // 检查运行限制条件是否满足
  const accountId = task.platformAccount
  // 昵称
  const nickname = task.nickName
  const cacheKey = `tk-live-home-follow_${accountId}`
  // 获取今日一共关注了多少人、回复了多少人
  const cacheData = tkLiveHomeFollowStore.get(cacheKey) || {}
  // 获取日期--yyyy-mm-dd格式。判断是不是今天。不是今天就重置数据
  const date = cacheData.date || ""
  const now = new Date()
  const nowDate = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`
  if (date !== nowDate) {
    cacheData.todayFollowNum = 0
    cacheData.todayReplyNum = 0
    cacheData.date = nowDate
    tkLiveHomeFollowStore.set(cacheKey, cacheData)
  }
  let todayFollowNum = cacheData.todayFollowNum || 0
  let todayReplyNum = cacheData.todayReplyNum || 0
  console.log("todayFollowNum===>", todayFollowNum)
  console.log("todayReplyNum===>", todayReplyNum)
  // 计算今天还可以关注的数量
  let todayLimitFollowNum = _limitNum - todayFollowNum
  let todayLimitReplyNum = _replyLimitNum - todayReplyNum
  console.log("todayLimitFollowNum===>", todayLimitFollowNum)
  console.log("todayLimitReplyNum===>", todayLimitReplyNum)
  // 计算今天还可以关注的数量
  if (todayLimitFollowNum <= 0 && todayLimitReplyNum <= 0) {
    console.log("今日关注数量、回复数量均已达上限-out")
    return
  }
  console.log("开始运行任务")
  // 解构task获取必要参数，兼容新旧格式
  const {
    tikTokDomain = "https://www.tiktok.com", // tikTok网站域名
  } = task || {}
  // 开始数据处理
  console.log(`开始处理账号(${index + 1}): ${task.account}`)
  await new Promise((resolve) => setTimeout(() => resolve(), 1000 * 10))
  await closeUnwantedPages(browser, ["www.tiktok.com", "start.adspower.net"])
  const page = await browser.newPage()
  await page.setViewport({ width: 1920, height: 1080 })
  console.log("我进来找直播间找粉丝了！=====>")
  try {
    // 获取搜索关键字
    // const searchKeysRes = await getRandomKeyWord(null, {
    //   headers: {
    //     "Content-Type": "application/x-www-form-urlencoded",
    //     "X-Platform": task.platformName,
    //     "X-ScriptApp": "browser",
    //     "X-Device-Id": task.deviceId,
    //     "tenant-id": task.tenantId,
    //   },
    // })
    const searchKeys = keywords || []
    console.log("searchKeys", searchKeys)
    // 随机取一个getRandomInteger
    const randomIndex = getRandomInteger(0, searchKeys.length - 1)
    const searchKey = searchKeys[randomIndex]
    console.log("searchKey", searchKey)
    // 如果关键词为空。直接退出
    if (!searchKey || searchKeys.length === 0) {
      console.log("后台返回的关键词为空。直接退出")
      return
    }
    await page.goto(tikTokDomain, { waitUntil: "networkidle2" })
    await new Promise((resolve) => setTimeout(() => resolve(), 1000 * 5))
    // 配置直播tab的选择器
    const liveTabSelector = 'button.TUXButton--secondary[aria-label="直播"]'
    // 等待直播tab按钮的出现，10秒
    await page.waitForSelector(liveTabSelector, { timeout: 10000 })
    // 获取直播tab按钮元素
    const liveTabBtn = await page.$(liveTabSelector)
    // 点击直播tab按钮
    await Promise.all([
      liveTabBtn.click(),
      page.waitForNavigation({ waitUntil: "networkidle0" }), // 等待页面完全加载
    ])
    // 等待页面加载完成--等待获取金币的控件出现
    const getCionSelector = 'button[data-e2e="LivePage-GetCoin"]'
    await page.waitForSelector(getCionSelector, { timeout: 10000 })
    const getCion = await page.$(getCionSelector)
    if (getCion) {
      // 进入到了直播间页面
      console.log("进入到了直播间页面")
      const button = await page.$('button.TUXButton[aria-label="返回"], button.TUXButton[aria-label="back"]')
      console.log("button", button)
      if (button) {
        // 获取button的坐标
        const buttonBox = await button.boundingBox()
        // 计算点击位置（元素中心）
        const x = buttonBox.x + buttonBox.width / 2
        const y = buttonBox.y + buttonBox.height / 2
        await page.mouse.click(x, y, { delay: 100 })
        await new Promise((resolve) => setTimeout(() => resolve(), 1000 * 2))
        // 等待搜索按钮出现
        await page.waitForSelector('button.TUXButton[role="searchbox"]', { timeout: 10000 })
        const searchBtn = await page.$('button.TUXButton[role="searchbox"]')
        console.log("searchBtn", searchBtn)
        const searchBtnBox = await searchBtn.boundingBox()
        console.log("searchBtnBox", searchBtnBox)
        // 计算点击位置（元素中心）
        const searchBtnX = searchBtnBox.x + searchBtnBox.width / 2
        console.log("searchBtnBox.x", searchBtnX < 0 ? searchBtnX + Math.abs(searchBtnX) + searchBtnBox.width / 2 : searchBtnX)
        const searchBtnY = searchBtnBox.y + searchBtnBox.height / 2
        await page.mouse.click(searchBtnX < 0 ? searchBtnX + Math.abs(searchBtnX) + searchBtnBox.width / 2 : searchBtnX, searchBtnY, {
          delay: 100,
        })
        await new Promise((resolve) => setTimeout(() => resolve(), 1000 * 2))
        // 此时页面会有一个聚焦的输入框。直接输入文字
        page.keyboard.type(searchKey, { delay: 200 })
        // 等待一秒
        await new Promise((resolve) => setTimeout(() => resolve(), 1000))
        // 按下回车键
        await page.keyboard.press("Enter")
        // 加载完成。开始获取直播间列表
        // 直播间列表选择器
        const liveListSelector = 'div[class="css-1soki6-DivItemContainerForSearch e19c29qe9"]'
        // 等待选择器出现
        await page.waitForSelector(liveListSelector, { timeout: 10000 * 2 })
        // 获取直播间列表元素
        const liveList = (await page.$$(liveListSelector)) || []
        console.log("liveList.length", liveList.length)
        // 过滤出可见的
        const visibleLiveList = []
        for (const item of liveList) {
          if (await item.boundingBox()) {
            visibleLiveList.push(item)
          }
        }
        // 用来记录已经处理过的博主直播间
        const handledLiveList = []
        // 是否已完成任务
        let isFinished = false
        // 是否已滚动到页面底部
        let isScrollToBottom = false
        // 循环执行，如果没有到底部、或者没有完成就可以继续执行
        while (true) {
          if (isFinished || isScrollToBottom) {
            console.log("今日关注数量、回复数量均已达上限-while")
            break
          }
          // 遍历直播间列表
          for (const visibleLiveItem of visibleLiveList) {
            console.log("visibleLiveItem===>", visibleLiveItem)
            // 获取visibleLiveItem下的img的src
            const imgSrc = await visibleLiveItem.evaluate((item) => {
              const img = item.querySelector("img")
              return img ? img.src : ""
            })
            console.log("imgSrc===>", imgSrc)
            // 获取当前环境Referer、User-Agent
            const userAgent = await page.evaluate(() => navigator.userAgent)
            const referer = "https://www.tiktok.com"
            const buffer = await downloadCdnResource(imgSrc, userAgent, referer, browser)
            const blob = new Blob([buffer], { type: "image/png" }, "img.png")
            // 创建一个 FormData 实例
            const formData = new FormData()
            formData.append("file", blob, {
              filename: "image.png",
              contentType: "image/png",
            })
            // 上传到oss生成url
            const ossUrl = await uploadImag(formData, { headers: { "Content-Type": "multipart/form-data" } })
            console.log("ossUrl====>", ossUrl)
            // 调接口判断是否符合关键词
            const checkImgRes = await checkKeyWordAndImg(
              {
                keyword: searchKey,
                imgUrl: ossUrl?.data,
              },
              {
                headers: {
                  "Content-Type": "application/json",
                  "X-Platform": task.platformName,
                  "X-ScriptApp": "browser",
                  "X-Device-Id": task.deviceId,
                  "tenant-id": task.tenantId,
                },
              }
            )
            console.log("checkImgRes", checkImgRes)
            if (checkImgRes.data) {
              console.log("图片符合关键词")
            } else {
              console.log("图片不符合关键词")
              continue
            }
            // 获取直播间博主账号。记录已经处理过了。循环过程中不要在处理了
            const accountSelector = 'p[data-e2e="search-card-user-unique-id"]'
            await page.waitForSelector(accountSelector, { timeout: 10000 })
            const accountDom = await visibleLiveItem.$(accountSelector)
            const account = await page.evaluate((el) => el.textContent.trim(), accountDom)
            console.log("直播间博主账号:", account)
            // 判断是否已经处理过，已经处理过的直接跳过
            if (handledLiveList.includes(account)) {
              console.log("已经处理过的直播间博主账号:", account)
              continue
            }
            // 添加到已经处理过的数组中
            handledLiveList.push(account)
            // 判断一下直播间是否符合关键词--后面待接入接口
            // 判断今天关注是否已达到上限、回复是否已达到上限。
            if (todayLimitFollowNum <= 0 && todayLimitReplyNum <= 0) {
              // 达到上限直接跳出循环
              console.log("今日关注数量、回复数量均已达上限-for")
              isFinished = true
              break
            }
            // 记录打开新标签页前的滚动位置
            const beforeNewPageScrollPosition = await page.evaluate(() => window.scrollY)
            // 没有达到上限就直接按顺序处理列表。
            // 使用ctrl+鼠标左键点击。开启新页面
            const newPage = await clickAndWaitForNewPage(browser, page, visibleLiveItem)
            if (newPage) {
              console.log("新页面已打开")
            } else {
              console.log("新页面创建失败或超时")
            }
            try {
              // 检查新页面是否成功创建
              if (!newPage) {
                console.log("新页面创建失败，跳过当前帖子")
                // 安全关闭新页面，防止页面未打开导致错误
                try {
                  if (newPage && !newPage.isClosed()) {
                    await newPage.close()
                    // 确保将焦点切回主页面，但保持滚动位置
                    await page.bringToFront()
                    // 恢复之前的滚动位置
                    await page.evaluate((position) => {
                      window.scrollTo({
                        top: position,
                        behavior: "instant", // 使用 instant 而不是 smooth 来避免滚动动画
                      })
                    }, beforeNewPageScrollPosition)
                  }
                } catch (error) {
                  console.error("关闭新页面发生错误:", error.message)
                  // 错误不影响主流程，继续执行
                }
                continue
              }
              // 等待新页面加载完成
              await newPage.waitForSelector("body") // 等待 body 加载完成
              // 切换到新页面
              await newPage.bringToFront() // 将新页面带到前端
              // 等待页面完全加载
              await new Promise((resolve) => setTimeout(resolve, 3000))
              // 等待观众席出现-选择器
              const audienceSelector = 'div[data-e2e="top-givers-header"]'
              await newPage.waitForSelector(audienceSelector, { timeout: 10000 })
              const audienceElement = await newPage.$(audienceSelector)
              console.log("audienceElement", audienceElement)
              // 获取观众席的中心坐标
              const audienceBox = await audienceElement.boundingBox()
              const audienceX = audienceBox.x + audienceBox.width / 2
              const audienceY = audienceBox.y + audienceBox.height / 2
              console.log("audienceX", audienceX)
              console.log("audienceY", audienceY)
              // 点击观众席
              await newPage.mouse.click(audienceX, audienceY, { delay: 100 })
              // 等待俩秒
              await new Promise((resolve) => setTimeout(() => resolve(), 1000 * 2))
              // 等待送礼物人列表
              const giverListSelector = 'div[class="tiktok-10g9jw4 e9rcsm17"]'
              await newPage.waitForSelector(giverListSelector, { timeout: 10000 })
              const giverList = (await newPage.$$(giverListSelector)) || []
              console.log("giverList.length", giverList.length)
              // 过滤出可见的
              const visibleGiverList = []
              for (const item of giverList) {
                if (await item.boundingBox()) {
                  visibleGiverList.push(item)
                }
              }
              console.log("visibleGiverList.length", visibleGiverList.length)
              // 遍历送礼物人列表
              for (const visibleGiverItem of visibleGiverList) {
                await new Promise((resolve) => setTimeout(() => resolve(), 1000 * 2))
                console.log("visibleGiverItem===>", visibleGiverItem)
                // 获取用户昵称
                const giverNicknameSelector = 'div[class="tiktok-r4vfug e9rcsm15"]'
                const giverNicknameElement = await visibleGiverItem.$(giverNicknameSelector)
                const giverNickname = await newPage.evaluate((el) => el.textContent.trim(), giverNicknameElement)
                console.log("送礼物人昵称:", giverNickname)
                // 获取用户已送出金币数量
                const giveCionCountSelector = 'div[class="tiktok-16o28mm e9rcsm16"]'
                await newPage.waitForSelector(giveCionCountSelector, { timeout: 10000 })
                const giveCionCountElement = await visibleGiverItem.$(giveCionCountSelector)
                const giveCionCount = await newPage.evaluate((el) => el.textContent.trim(), giveCionCountElement)
                console.log("送礼物人已送出金币数量:", giveCionCount && parseAbbreviatedNumber(giveCionCount))
                // 判断送出的金币是否符合条件
                if (parseAbbreviatedNumber(giveCionCount) < _liveHomeSendCionNumLimit) {
                  console.log("送出的金币数量不符合条件")
                  continue
                }
                // 符合条件的继续处理
                // 点击用户的昵称
                const giverNicknameBox = await giverNicknameElement.boundingBox()
                console.log("giverNicknameBox====>", giverNicknameBox)
                const giverNicknameX = giverNicknameBox.x + giverNicknameBox.width / 2
                const giverNicknameY = giverNicknameBox.y + giverNicknameBox.height / 2
                console.log("giverNicknameX", giverNicknameX)
                console.log("giverNicknameY", giverNicknameY)
                await newPage.mouse.click(giverNicknameX, giverNicknameY, { delay: 100 })
                await new Promise((resolve) => setTimeout(() => resolve(), 1000 * 2))
                // 等待弹出用户详情列表
                const userDetailListSelector = 'a[data-testid="user-card-avatar"]'
                await newPage.waitForSelector(userDetailListSelector, { timeout: 10000 })
                const userDetailListElement = await newPage.$(userDetailListSelector)
                console.log("userDetailListElement", userDetailListElement)
                // 记录打开新标签页前的滚动位置
                const userDetailBeforeNewPageScrollPosition = await page.evaluate(() => window.scrollY)
                // 使用ctrl+鼠标左键点击。
                const userDetailPage = await clickAndWaitForNewPage(browser, newPage, userDetailListElement)
                if (userDetailPage) {
                  console.log("用户详情-新页面已打开")
                } else {
                  console.log("用户详情-新页面创建失败或超时")
                }
                try {
                  // 检查新页面是否成功创建
                  if (!userDetailPage) {
                    console.log("新页面创建失败，跳过当前帖子")
                    // 安全关闭新页面，防止页面未打开导致错误
                    try {
                      if (userDetailPage && !userDetailPage.isClosed()) {
                        await userDetailPage.close()
                        // 确保将焦点切回主页面，但保持滚动位置
                        await newPage.bringToFront()
                        // 恢复之前的滚动位置
                        await newPage.evaluate((position) => {
                          window.scrollTo({
                            top: position,
                            behavior: "instant", // 使用 instant 而不是 smooth 来避免滚动动画
                          })
                        }, userDetailBeforeNewPageScrollPosition)
                      }
                    } catch (error) {
                      console.error("关闭新页面发生错误:", error.message)
                      // 错误不影响主流程，继续执行
                    }
                    continue
                  }
                  // 等待新页面加载完成
                  await userDetailPage.waitForSelector("body") // 等待 body 加载完成
                  // 切换到新页面
                  await userDetailPage.bringToFront() // 将新页面带到前端

                  // 等待页面完全加载
                  await new Promise((resolve) => setTimeout(resolve, 3000))
                  // 获取账号、昵称
                  const fansAccountSelector = 'h1[data-e2e="user-title"]'
                  const fansNickNameSelector = 'h2[data-e2e="user-subtitle"]'
                  await userDetailPage.waitForSelector(fansAccountSelector, { timeout: 10000 })
                  await userDetailPage.waitForSelector(fansNickNameSelector, { timeout: 10000 })
                  const fansAccountElement = await userDetailPage.$(fansAccountSelector)
                  const fansNickNameElement = await userDetailPage.$(fansNickNameSelector)
                  const fansAccount = await userDetailPage.evaluate((el) => el.textContent.trim(), fansAccountElement)
                  const fansNickName = await userDetailPage.evaluate((el) => el.textContent.trim(), fansNickNameElement)
                  console.log("fansAccount", fansAccount)
                  console.log("fansNickName", fansNickName)
                  if (nickname === fansNickName) {
                    // 自己出现在列表中 直接跳过
                    console.log("自己出现在列表。针对自己不操作")
                    continue
                  }
                  // 如果粉丝已经处理过。直接跳过
                  let uploadRes = null
                  // 1. 保存当前页面的 URL
                  const currentUrl = userDetailPage.url()
                  try {
                    // 获取头像的父元素
                    const avatarParentSelector = "span.e1vl87hj2"
                    await userDetailPage.waitForSelector(avatarParentSelector, { timeout: 10000 })
                    const avatarParent = await userDetailPage.$(avatarParentSelector)
                    // 获取头像
                    // 获取头像图片（需要根据实际页面元素调整选择器）
                    const avatarElement = await avatarParent.$('img[class="css-1zpj2q-ImgAvatar e1e9er4e1"]')
                    let avatarBuffer = null
                    if (avatarElement) {
                      const avatarSrc = await avatarElement.evaluate((img) => img.src)
                      const response = await userDetailPage.goto(avatarSrc)
                      avatarBuffer = await response.buffer()
                    }
                    const blob = new Blob([avatarBuffer], { type: "image/png" }, "avatar.png")

                    const formData = new FormData()
                    formData.append("file", blob, {
                      filename: "image.png",
                      contentType: "image/png",
                    })

                    uploadRes = await uploadImag(formData, { headers: { "Content-Type": "multipart/form-data" } })
                    console.log("上传头像返回结果：", uploadRes.data)
                    // 3. 跳转回原来的页面
                    await userDetailPage.goto(currentUrl)
                  } catch (error) {
                    // 3. 跳转回原来的页面
                    await userDetailPage.goto(currentUrl)
                    console.log("获取粉丝头像报错了", error)
                  }
                  // 这里可以请求接口判断是否关注过。已经在库里面的就不用关注了！！
                  try {
                    const selectFansRes = await selectFans(
                      {
                        account: fansAccount,
                      },
                      {
                        headers: {
                          "Content-Type": "application/x-www-form-urlencoded",
                          "X-Platform": task.platformName,
                          "X-ScriptApp": "browser",
                          "X-Device-Id": task.deviceId,
                          "tenant-id": task.tenantId,
                        },
                      }
                    )
                    console.log("selectFansRes", selectFansRes)
                    if (!selectFansRes.data && todayLimitFollowNum > 0) {
                      // 获取关注按钮
                      const followBtnSelector = 'button[data-e2e="follow-button"]'
                      await userDetailPage.waitForSelector(followBtnSelector, { timeout: 10000 })
                      const followBtnElement = await userDetailPage.$(followBtnSelector)
                      // 点击关注
                      console.log("followBtnElement", followBtnElement)
                      await followBtnElement.click()
                      todayLimitFollowNum = todayLimitFollowNum - 1
                      todayFollowNum = todayFollowNum + 1
                      console.log("今日关注数量：", todayFollowNum, " 个人", ` ${nowDate}`)
                      console.log("今日还能关注：", todayLimitFollowNum, " 个人", ` ${nowDate}`)
                      // 保存粉丝到后台
                      const saveFansRes = await insertOrUpdateFans(
                        {
                          fansAccount: fansAccount,
                          fansNickName: fansNickName,
                          operatorName: task.host.name,
                          platformAccount: task.platformAccount,
                          avatarUrl: uploadRes.data,
                        },
                        {
                          headers: {
                            "Content-Type": "application/json",
                            "X-Platform": task.platformName,
                            "X-ScriptApp": "browser",
                            "X-Device-Id": task.deviceId,
                            "tenant-id": task.tenantId,
                          },
                        }
                      )
                      console.log("saveFansRes", saveFansRes)
                      // 存一份本地缓存-tkLiveHomeFollowStore
                      tkLiveHomeFollowStore.set(cacheKey, {
                        todayReplyNum: todayReplyNum,
                        todayLimitReplyNum: todayLimitReplyNum,
                        todayFollowNum: todayFollowNum,
                        todayLimitFollowNum: todayLimitFollowNum,
                        date: nowDate,
                      })
                      console.log("本地缓存成功----关注")
                      await new Promise((resolve) => setTimeout(() => resolve(), 1000 * 2))
                    }
                    if (selectFansRes.data) {
                      console.log("当前粉丝处理过不再破冰")
                      continue
                    }
                  } catch (error) {
                    console.error("关注失败:", error)
                  }
                  await new Promise((resolve) => setTimeout(() => resolve(), 1000 * 2))
                  if (todayLimitReplyNum > 0) {
                    let content = ""
                    // 获取这个用户的历史聊天记录。如果有直接不回复
                    try {
                      const massageRes = await getChatRecord(
                        {
                          fansAccount: fansAccount,
                          limitNum: 1,
                        },
                        {
                          headers: {
                            "Content-Type": "application/x-www-form-urlencoded",
                            "X-Platform": task.platformName,
                            "X-ScriptApp": "browser",
                            "X-Device-Id": task.deviceId,
                            "tenant-id": task.tenantId,
                          },
                        }
                      )
                      console.log("massageRes===>", massageRes)
                      if (!massageRes.data || massageRes.data.length > 0) {
                        // 如果有消息直接跳过
                        console.log("当前用户已经和机器人聊过天了，不再破冰")
                        continue
                      }
                      // 保存粉丝到后台
                      const saveFansRes = await insertOrUpdateFans(
                        {
                          fansAccount: fansAccount,
                          fansNickName: fansNickName,
                          operatorName: task.host.name,
                          platformAccount: task.platformAccount,
                        },
                        {
                          headers: {
                            "Content-Type": "application/json",
                            "X-Platform": task.platformName,
                            "X-ScriptApp": "browser",
                            "X-Device-Id": task.deviceId,
                            "tenant-id": task.tenantId,
                          },
                        }
                      )
                      console.log("saveFansRes", saveFansRes)
                      // 调接口生成ai回复
                      const aiReplyRes = await generateChatContent(
                        {
                          fansAccount,
                          platformAccount: task.platformAccount,
                          msgFromFans: "",
                          chatType: 0,
                        },
                        {
                          headers: {
                            "Content-Type": "application/json",
                            "X-Platform": task.platformName,
                            "X-ScriptApp": "browser",
                            "X-Device-Id": task.deviceId,
                            "tenant-id": task.tenantId,
                          },
                        }
                      )
                      console.log("aiReplyRes===>", aiReplyRes)
                      let relay = aiReplyRes?.data?.responseText
                      if (relay) {
                        content = replacePlaceholder(relay, configMap, task)
                      } else {
                        console.log("ai回复失败，请检查配置")
                      }
                    } catch (error) {
                      console.log("chat-error", error)
                    }
                    if (content) {
                      // 获取发消息按钮
                      const messageBtnSelector = 'button[data-e2e="message-button"]'
                      await userDetailPage.waitForSelector(messageBtnSelector, { timeout: 10000 })
                      const messageBtnElement = await userDetailPage.$(messageBtnSelector)
                      // 点击发消息
                      await messageBtnElement.click()
                      await new Promise((resolve) => setTimeout(() => resolve(), 1000 * 2))
                      // 等待input输入框出现
                      const inputSelector = 'div[data-e2e="message-input-area"]'
                      await userDetailPage.waitForSelector(inputSelector, { timeout: 10000 })
                      // 获取中心坐标并且点击
                      const inputElement = await userDetailPage.$(inputSelector)
                      const inputBox = await inputElement.boundingBox()
                      const inputX = inputBox.x + inputBox.width / 2
                      const inputY = inputBox.y + inputBox.height / 2
                      console.log("inputX", inputX)
                      console.log("inputY", inputY)
                      await new Promise((resolve) => setTimeout(() => resolve(), 1000 * 2))
                      await userDetailPage.mouse.click(inputX, inputY, { delay: 100 })
                      // 聚焦了直接输入文字
                      await userDetailPage.keyboard.type(content, { delay: 200 })
                      // 按下回车键
                      await userDetailPage.keyboard.press("Enter")
                      await new Promise((resolve) => setTimeout(() => resolve(), 1000 * 2))
                      todayLimitReplyNum = todayLimitReplyNum - 1
                      todayReplyNum = todayReplyNum + 1
                      console.log("今日回复数量：", todayReplyNum, " 个人", ` ${nowDate}`)
                      console.log("今日还能回复：", todayLimitReplyNum, " 个人", ` ${nowDate}`)
                      // 存一份本地缓存-tkLiveHomeFollowStore
                      tkLiveHomeFollowStore.set(cacheKey, {
                        todayReplyNum: todayReplyNum,
                        todayLimitReplyNum: todayLimitReplyNum,
                        todayFollowNum: todayFollowNum,
                        todayLimitFollowNum: todayLimitFollowNum,
                        date: nowDate,
                      })
                      console.log("本地缓存成功----回复")
                      try {
                        const missMsgs = [
                          {
                            user: fansAccount,
                            role: "assistant",
                            flag: 1,
                            content: content,
                            appVersion: "1.0.0",
                            operatorName: task.host.name,
                            clientParameter: JSON.stringify({
                              // 配置configMap的配置信息发送给后台
                              operator_line: task.host.line,
                              host: task.host.name,
                            }),
                            isCompleteAuto: true,
                          },
                        ]
                        // 保存聊天记录到后台
                        const saveChatMessage = await saveChatRecord(
                          {
                            fansAccount,
                            missingMsgs: missMsgs,
                            operatorName: task.host.name,
                            nonce: generatePositiveInt64(),
                          },
                          {
                            headers: {
                              "Content-Type": "application/json",
                              "X-Platform": task.platformName,
                              "X-ScriptApp": "browser",
                              "X-Device-Id": task.deviceId,
                              "tenant-id": task.tenantId,
                            },
                          }
                        )
                        console.log("saveChatMessage", saveChatMessage)
                      } catch (error) {
                        console.log("saveChatMessage-error", error)
                      }
                    }
                  }
                  // 判断一下限制是否到达，如果到达就不再继续执行
                  if (todayLimitFollowNum <= 0 && todayLimitReplyNum <= 0) {
                    console.log("今日限制已经到达，不再执行")
                    isFinished = true
                    break
                  }
                  await new Promise((resolve) => setTimeout(() => resolve(), 1000 * 2))
                  try {
                    if (userDetailPage && !userDetailPage.isClosed()) {
                      await userDetailPage.close()
                      // 确保将焦点切回主页面，但保持滚动位置
                      await newPage.bringToFront()
                      // 关闭详情弹窗
                      const closeDetailSelector = 'div[class="tiktok-1ncf7vi e1yzsfo98"]'
                      await newPage.waitForSelector(closeDetailSelector, { timeout: 10000 })
                      const closeDetailElement = await newPage.$(closeDetailSelector)
                      // 获取中心点
                      const closeDetailBox = await closeDetailElement.boundingBox()
                      const closeDetailX = closeDetailBox.x + closeDetailBox.width / 2
                      const closeDetailY = closeDetailBox.y + closeDetailBox.height / 2
                      console.log("closeDetailX", closeDetailX)
                      console.log("closeDetailY", closeDetailY)
                      await newPage.mouse.click(closeDetailX, closeDetailY, { delay: 100 })
                      // 恢复之前的滚动位置
                      await newPage.evaluate((position) => {
                        window.scrollTo({
                          top: position,
                          behavior: "instant", // 使用 instant 而不是 smooth 来避免滚动动画
                        })
                      }, beforeNewPageScrollPosition)
                    }
                  } catch (error) {
                    console.error("关闭新页面发生错误:", error.message)
                    // 错误不影响主流程，继续执行
                  }

                  await new Promise((resolve) => setTimeout(() => resolve(), 1000 * 2))
                } catch (error) {
                  // 安全关闭新页面，防止页面未打开导致错误
                  try {
                    if (newPage && !newPage.isClosed()) {
                      await newPage.close()
                      // 确保将焦点切回主页面，但保持滚动位置
                      await page.bringToFront()
                      // 恢复之前的滚动位置
                      await page.evaluate((position) => {
                        window.scrollTo({
                          top: position,
                          behavior: "instant", // 使用 instant 而不是 smooth 来避免滚动动画
                        })
                      }, beforeNewPageScrollPosition)
                    }
                  } catch (error) {
                    console.error("关闭新页面发生错误:", error.message)
                    // 错误不影响主流程，继续执行
                  }
                }
              }
              try {
                if (newPage && !newPage.isClosed()) {
                  await newPage.close()
                  // 确保将焦点切回主页面，但保持滚动位置
                  await page.bringToFront()
                  // 恢复之前的滚动位置
                  await page.evaluate((position) => {
                    window.scrollTo({
                      top: position,
                      behavior: "instant", // 使用 instant 而不是 smooth 来避免滚动动画
                    })
                  }, beforeNewPageScrollPosition)
                }
              } catch (error) {
                console.error("关闭新页面发生错误:", error.message)
                // 错误不影响主流程，继续执行
              }

              await new Promise((resolve) => setTimeout(() => resolve(), 1000 * 2))
            } catch (error) {
              // 安全关闭新页面，防止页面未打开导致错误
              try {
                if (newPage && !newPage.isClosed()) {
                  await newPage.close()
                  // 确保将焦点切回主页面，但保持滚动位置
                  await page.bringToFront()
                  // 恢复之前的滚动位置
                  await page.evaluate((position) => {
                    window.scrollTo({
                      top: position,
                      behavior: "instant", // 使用 instant 而不是 smooth 来避免滚动动画
                    })
                  }, beforeNewPageScrollPosition)
                }
              } catch (error) {
                console.error("关闭新页面发生错误:", error.message)
                // 错误不影响主流程，继续执行
              }
            }
          }
          // 滑动加载更多
          isScrollToBottom = await scrollToBottom(100, page)
          await new Promise((resolve) => setTimeout(() => resolve(), 1000 * 20))
        }
      }
    }
  } catch (error) {
    console.error("Error occurred during processing:", error)
    result.success = false
    result.message = `执行出错: ${error.message}`
  } finally {
  }
  return result
}
// ctrl+点击开启一个新的页面
async function clickAndWaitForNewPage(browser, page, visibleLiveItem, timeout = 10000) {
  try {
    // 先记录已有的 target 数量
    const existingTargetIds = new Set(browser.targets().map((t) => t._targetId))

    // 创建一个等待新页面的 Promise（使用 waitForTarget 更稳）
    const newPagePromise = new Promise((resolve) => {
      const timer = setTimeout(() => {
        console.log("等待新页面创建超时")
        resolve(null)
      }, timeout)

      browser.on("targetcreated", async (target) => {
        if (!existingTargetIds.has(target._targetId) && target.type() === "page") {
          const newPage = await target.page()
          clearTimeout(timer)
          resolve(newPage)
        }
      })
    })

    // 执行点击操作
    console.log("Control===1")
    await new Promise((r) => setTimeout(r, 2000))

    const initialBox = await visibleLiveItem.boundingBox()
    await new Promise((r) => setTimeout(r, 500))
    const finalBox = await visibleLiveItem.boundingBox()

    if (initialBox && finalBox && initialBox.x === finalBox.x && initialBox.y === finalBox.y) {
      console.log("Element is stable")
    }

    await page.evaluate((el) => el.scrollIntoView({ behavior: "smooth", block: "center" }), visibleLiveItem)
    await new Promise((r) => setTimeout(r, 500))

    const box = await visibleLiveItem.boundingBox()
    if (!box) throw new Error("Element not found or not visible")

    const x = box.x + box.width / 2
    const y = box.y + box.height / 2
    console.log("Control,x,y====>", x, y)
    await page.keyboard.down("Control")
    console.log("Control===2")
    await new Promise((r) => setTimeout(r, 100))

    await page.mouse.click(x, y, { delay: 100 })
    console.log("Control===3")
    await new Promise((r) => setTimeout(r, 100))

    await page.keyboard.up("Control")
    await new Promise((r) => setTimeout(r, 1000))

    const newPage = await newPagePromise
    return newPage
  } catch (err) {
    console.error("点击并等待新页面时出错:", err)
    return null
  }
}
async function scrollToBottom(step = 100, page) {
  const scrollResult = await page.evaluate(async (step) => {
    const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms))

    // 获取滚动前的位置
    const beforeScrollY = window.scrollY
    console.log("滚动前位置:", beforeScrollY)

    // 计算合理的滚动步长
    const scrollStep = step + Math.random() * step * 0.5 // 每次滚动 100-150px，减小随机性
    const scrollDelay = 50 + Math.random() * 100 // 每次滚动间隔 50-150ms，更流畅

    // 使用相对滚动，从当前位置滚动一定距离，而不是绝对位置
    window.scrollBy({
      top: scrollStep,
      behavior: "smooth", // 使用平滑滚动
    })

    await delay(scrollDelay)

    // 模拟偶尔停顿，但减少概率
    if (Math.random() < 0.1) {
      const pauseTime = 500 + Math.random() * 1000 // 0.5-1.5秒的停顿，缩短停顿时间
      await delay(pauseTime)
    }

    // 获取滚动后的位置，并确认滚动是否有效
    const afterScrollY = window.scrollY
    console.log("滚动后位置:", afterScrollY)

    // 计算滚动是否有效（是否真的向下滚动了）
    const scrolledEffectively = afterScrollY > beforeScrollY

    // 判断是否到底部
    const reachedBottom = document.documentElement.scrollTop + window.innerHeight >= document.documentElement.scrollHeight - 10 // 添加10px的容差

    return {
      reachedBottom,
      scrolledEffectively,
      beforePosition: beforeScrollY,
      afterPosition: afterScrollY,
    }
  }, step)

  // 记录滚动结果
  console.log(`滚动结果: 到达底部=${scrollResult.reachedBottom}, 有效滚动=${scrollResult.scrolledEffectively}, 位置变化=${scrollResult.beforePosition} -> ${scrollResult.afterPosition}`)

  // 如果滚动无效，可以认为已经到底
  if (!scrollResult.scrolledEffectively) {
    console.log("滚动无效，可能已经到底或遇到阻碍")
  }

  return scrollResult.reachedBottom
}
/**
 * 将带单位的数字字符串（如 "14.6K", "5.6M", "15B"）转换为实际数字
 * 支持单位（不区分大小写）：K（千）、M（百万）、B（十亿）、T（万亿）
 * @param {string} inputStr
 * @returns {number}
 */
function parseAbbreviatedNumber(inputStr) {
  if (typeof inputStr !== "string") return NaN

  const units = {
    k: 1e3,
    m: 1e6,
    b: 1e9,
    t: 1e12,
  }

  const match = inputStr.trim().match(/^([\d.,]+)\s*([kmgtb])?$/i)
  if (!match) return NaN

  let [, numberStr, unit] = match
  numberStr = numberStr.replace(/,/g, "") // 去掉逗号
  const num = parseFloat(numberStr)
  if (isNaN(num)) return NaN

  if (!unit) return num // 没有单位，直接返回数字

  const multiplier = units[unit.toLowerCase()] || 1
  return num * multiplier
}

